home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Frameworks / Hsoi's App Shell 1.0a4 / Hsoi's App Shell Source / HASEventDispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-28  |  14.5 KB  |  500 lines  |  [TEXT/CWIE]

  1. /*
  2.     HASEventDispatch.c from Hsoi's App Shell © 1995-1997 John C. Daub.  All rights reserved.
  3.  
  4.     This file contains one function to deal with events (except AppleEvents, that's
  5.     another file).  This is just the "dispatch" file; the functions to actually
  6.     deal with each event are located elsewhere.  But this is the "chain of command"
  7.     where all things go from.
  8. */
  9.  
  10. #pragma mark ••• #includes •••
  11.  
  12. #ifndef _WASTE_
  13. #include "WASTE.h"
  14. #endif
  15. #include "HASGlobals.h"
  16. #ifndef __HSOIS_APP_SHELL__
  17. #include "HASMain.h"
  18. #endif
  19. #include "HASMenus.h"
  20. #include "HASHelp.h"
  21. #include "HASMenuWindows.h"
  22. #include "HASEventDispatch.h"
  23. #include "HASMiscEvents.h"
  24. #include "HASCoolAboutBox.h"
  25. #include "HASWindows.h"
  26. #include "HASUtilities.h"
  27. #include "HASUtilCursors.h"
  28. #include "HASSoundSpeech.h"
  29. #include "HASDialogs.h"
  30.  
  31. #ifndef _WASTEOBJECTS_
  32. #include "WASTE_Objects.h"
  33. #endif
  34.  
  35. #pragma mark -
  36.  
  37. /*
  38.  *    HsoiDoEvent() is all there is here:  as soon as an event is snagged via WaitNextEvent()
  39.  *    in the main event loop, it's passed here for dispatching
  40.  */
  41.  
  42.  
  43. void    HsoiDoEvent( const EventRecord *event )
  44. {
  45.     short        myError;
  46.     short        windowPart;
  47.     WindowRef    window;
  48.     char        key;
  49.     Point        mountPoint;
  50.     Boolean        isCmdKey;
  51.     
  52.     
  53.     // switch on what the event was...
  54.     
  55.     switch( event->what )
  56.     {
  57.             
  58.         // no need to handle null events here, due to how the main event loop is written.
  59.         
  60.         // networkEvt, app1Evt, app2Evt are all obsolete events, so we don't need to
  61.         // handle them.  app4Evt has been renamed to osEvt.  There is the app3Evt
  62.         // which is something that we aren't handling...it's an event type that the
  63.         // application can set for itself (like if your application needs to insert events
  64.         // into the event queue and needs to handle its own type of event, you can use
  65.         // the app3Evt event type as your switch case for this).  It really still is
  66.         // an obsolete event, but you probably could get away in using it, if you wanted to,
  67.         // by just #define-ing a few things, like #define app3Evt 14, and #define app3EvtMask
  68.         // 0x4000  or something.  but, i doubt you'll need this (it's not in my Universal Headers).
  69.         
  70.     
  71.         // take care of AppleEvents
  72.         
  73.         case kHighLevelEvent:
  74.             AEProcessAppleEvent( event );
  75.         break;
  76.  
  77.         // end case kHighLevelEvent
  78.         
  79.         
  80.         // take care of mouseDown events.
  81.         
  82.         case mouseDown:
  83.         
  84.             // find where the mouseDown occured.
  85.             
  86.             windowPart = FindWindow( event->where, &window );
  87.             
  88.             //    handle if we're in a modal/movable modal dialog
  89.             
  90.             if ( gInModalState && (window != FrontWindow() ) && ( windowPart != inMenuBar) )
  91.             {
  92.                 SysBeep( 5 );
  93.                 return;
  94.             }
  95.             
  96.             switch( windowPart )
  97.             {
  98.                 // if they click in the menu bar...
  99.             
  100.                 case inMenuBar:
  101.                 {
  102.                     long        menuResult;
  103.                     Str255        originalMenuString, HASMenuString;
  104.                     Boolean        textChanged;
  105.                     MenuRef        appleMenuH = GetMenuHandle( mApple );
  106.                     
  107.                     //  prepare menu items first    
  108.                     
  109.                     HsoiAdjustMenus();
  110.                     
  111.                     // to prep for the "easter egg", if the user has the option
  112.                     // key held down (opt-click on the About will do the easter egg)
  113.                     // we want to text of the About item to change.  Normally it
  114.                     // should say "About xxx..." where xxx is the name of the
  115.                     // app you've written.  But, this easter egg is something for
  116.                     // Hsoi's App Shell (as per the rules/regs/usage/etc things).
  117.                     // So, let's change the text of the About menu item to reflect
  118.                     // that change.
  119.                     
  120.                     // first, let's see if the opt key is held down, else forget it
  121.                     
  122.                     if ( event->modifiers & optionKey )
  123.                     {
  124.                         // ok. it's a go, so let's save the original menu text
  125.                         
  126.                         GetMenuItemText( appleMenuH, iAbout, originalMenuString );
  127.                         
  128.                         // get the "About HAS" string from the resource fork
  129.                         
  130.                         GetIndString( HASMenuString, rCoolAboutBoxMenuItemStrings, strAboutHAS );
  131.                         
  132.                         // change the menu item text
  133.                         
  134.                         SetMenuItemText( appleMenuH, iAbout, HASMenuString );
  135.                     
  136.                         // note that the text was changed (so we can change it back )
  137.                         
  138.                         textChanged = true;
  139.                     }
  140.                     else
  141.                     {
  142.                         // text wasnt' changed...no need to change it back
  143.                         
  144.                         textChanged = false;
  145.                     }
  146.                     
  147.                     // find out the menu and the item clicked on
  148.                     
  149.                     menuResult = MenuSelect( event->where );
  150.                     
  151.                     // for the cool about box, they can see that if they click on
  152.                     // About with the option key down, so let's check for that.
  153.                     
  154.                     // it's kinda like an Easter Egg :-)
  155.                     
  156.                     if ( (HiWrd( menuResult ) == mApple) &&
  157.                          (LoWrd( menuResult ) == iAbout) &&
  158.                          (event->modifiers & optionKey ) )
  159.                     {
  160.                         HsoiDoCoolAboutBox();
  161.                                                                         
  162.                         HiliteMenu( 0 );
  163.                     }
  164.                     else
  165.                         HsoiDoMenuCommand( menuResult );
  166.                     
  167.                     // see if we have to change the about menu item text back, if so, change it back
  168.                     
  169.                     if ( textChanged )
  170.                         SetMenuItemText( appleMenuH, iAbout, originalMenuString );
  171.                         
  172.                 }
  173.                 break;
  174.                                 
  175.                 // if they click in a system window (like a DA or something)
  176.                 
  177.                 case inSysWindow:
  178.                 // ?? SystemClick() should be defined as
  179.                 // SystemClick( const EventRecord *, WindowRef ) (Marco discovered this
  180.                 // inconsistancy in Apple's Universal Headers 2.1)
  181.                     SystemClick( event, (WindowPtr)window );
  182.                 break;
  183.                 
  184.                 // if they click in the content region of a window...
  185.                 
  186.                 case inContent:
  187.                 {    
  188.                     if ( HsoiDoContentClick( event->where, event, window ) )
  189.                     {
  190.                         SelectWindow( window );
  191.                     
  192.                         // force the clipboard window to redraw/update
  193.                         if ( HsoiIsClipboardWindow( window ) )
  194.                         {
  195.                             WEReference we = HsoiGetWindowWE( window );
  196.                             Str255    tempStr = NIL_STRING;
  197.                             
  198.                             HideWindow( window );
  199.                             
  200.                             WEFeatureFlag( weFReadOnly, weBitClear, we );
  201.             
  202.                             if ( WECanPaste( we ) )
  203.                             {    
  204.                                 // since WEPaste (and it's call to WEInsert) and WEDElete could take a long time
  205.                                 // (like if the scrap is HUGE) can take a long time to perform, let's spin
  206.                                 // our cursor.  Again (as with just about all my uses of the VBL spinning cursor)
  207.                                 // this is good to do cause otherwise it sorta looks like the computer froze up
  208.                                 // and this could worry the user...if the cursor is spinning, at least the
  209.                                 // user is getting some feedback that the computer is running...and heck, if
  210.                                 // we know the cursor is supposed to spin and it freezes up, then we probably
  211.                                 // do have some sort of bad error and the computer is probably fubar
  212.                                 
  213.                                 // start the VBL spinning cursor
  214.             
  215.                                 HsoiStartVBLSpinning();
  216.             
  217.                                 // let's take whatever's currently in the window and delete it
  218.             
  219.                                 WESetSelection( 0, MAXLONG, we );
  220.                                 WEDelete( we );
  221.         
  222.                                 // now paste whatever's on the scrap into the window
  223.     
  224.                                 //WEPaste( we );
  225.                                 WEObjectsPaste( we );
  226.             
  227.                                 // and stop the spinning cursor
  228.             
  229.                                 HsoiStopVBLSpinning();
  230.                             }
  231.                             else
  232.                             {
  233.                                 // we shouldn't use the prefs error alert box for this, but it's the "cleanest"
  234.                                 // error box for use to use for this.  this will change when i get the error handlers
  235.                                 // all re-written
  236.                                 
  237.                                 GetIndString( tempStr, rClipboardWindowStrings, strClipboardEmpty );
  238.                                 ParamText( tempStr, NIL_STRING, NIL_STRING, NIL_STRING );
  239.                                 NoteAlert( rPrefsErrorAlert, HsoiGetMyStandardDialogFilter() );
  240.                                 
  241.                                 // and through testing some other stuff, i found this as a bug...if !canPaste,
  242.                                 // and there was something already in the window (like from a previous "sucessful"
  243.                                 // ShowClipboard), the "old" window contents showed up!  not good...we should
  244.                                 // make sure the window contains nothing.  so, simple fix:
  245.                                 
  246.                                 // and going with the above ( if canPaste ) thing about a long time, since
  247.                                 // WEDelete could take a bit to do, let's sping the cursor
  248.                                 
  249.                                 HsoiStartVBLSpinning();
  250.                                 
  251.                                 WESetSelection( 0, MAXLONG, we );
  252.                                 WEDelete( we );
  253.                                 
  254.                                 HsoiStopVBLSpinning();
  255.                             }
  256.         
  257.                             // set the read-only bit.  users should not be able to cut/copy/paste to/from this
  258.                             // window for obvious reasons
  259.                             
  260.                             WEFeatureFlag( weFReadOnly, weBitSet, we );
  261.                         
  262.                             // now we can show it and all that good stuff
  263.                             
  264.                             ShowWindow( window );
  265.                             SelectWindow( window );
  266.                             SetPortWindowPort( window );
  267.     
  268.                         
  269.                         }
  270.                     }
  271.                 }    
  272.                 break;
  273.  
  274.                 // if they click in the drag region of the window...
  275.                 
  276.                 case inDrag:
  277.                     HsoiDoDrag( event->where, window );
  278.                 break;
  279.                 
  280.                 // if they click in the grow box...
  281.                     
  282.                 case inGrow:
  283.                     HsoiDoGrow( event->where, window );
  284.                 break;
  285.                     
  286.                 // if they click in the go away box...
  287.                 
  288.                 case inGoAway:
  289.                     if ( TrackGoAway( window, event->where ) && !gHiliting )
  290.                         HsoiDoClose( closingWindow, savingAsk, window );                        
  291.                 break;
  292.                 
  293.                 // if they click in the zoom box...
  294.                 
  295.                 case inZoomIn:
  296.                 case inZoomOut:
  297.                     if ( TrackBox( window, event->where, windowPart ) )
  298.                         HsoiDoZoom( windowPart, window );
  299.             
  300.                 break;
  301.                 
  302.             } // end switch( windowPart )
  303.         break;
  304.             
  305.             // end case mouseDown
  306.         
  307.         // and now, the next favorite event of the day, the keyDown.  now, I don't need
  308.         // to specially handle autoKey's, so I can nicely handle these 2 events with
  309.         // one set of code.  However, if you have some differences in your code that
  310.         // calls for special handling of keyDowns and autoKey's, you can always
  311.         // double this code, or you could even write your switch statement without
  312.         // a "break" in there to let things fall through...what programming skills!!! :-)
  313.         
  314.         case keyDown:
  315.         case autoKey:
  316.         
  317.             // extract what key was pressed from the EventRecord.
  318.             
  319.             key = event->message & charCodeMask;
  320.             
  321.             // is this a command+key combo?
  322.             
  323.             isCmdKey = (BAND(event->modifiers, cmdKey) != 0);
  324.             
  325.             //    map function keys to the equivalent command+key combos
  326.             //    note that all function keys generate the same character code, i.e. 0x10
  327.             //    so we have to do a little ferretting around to find out exactly which
  328.             //    function key was pressed...
  329.             
  330.             if ( key == 0x10 )    // if it's a function key, find out which on
  331.             {
  332.                 isCmdKey = true;
  333.             
  334.                 // now, with a little funky bit shifting, we can figure out exactly
  335.                 // what function key was pressed.  then, we can map that key to do
  336.                 // whatever action we want.  in this case, we'll do stuff like the
  337.                 // little template that comes with Apple keyboards has: F1 - Undo,
  338.                 // F2 - cut, F3 - copy, and F4, paste.  but of course, you can have
  339.                 // your function keys do whatever.
  340.                 
  341.                 switch( BSR( BAND( event->message, keyCodeMask ), 8 ) )
  342.                 {
  343.                     case keyF1:
  344.                         key = 'z';
  345.                     break;
  346.                     
  347.                     case keyF2:
  348.                         key = 'x';
  349.                     break;
  350.                     
  351.                     case keyF3:
  352.                         key = 'c';
  353.                     break;
  354.                     
  355.                     case keyF4:
  356.                         key = 'v';
  357.                     break;
  358.                     
  359.                     default:
  360.                         key = 0;
  361.                 
  362.                 }// end switch BSR( BAND( event->message, keyCodeMask), 8 ) 
  363.             
  364.             } // end if ( key == 0x10 )
  365.             
  366.             // now, either it wasn't a function key that was pressed, or it was a function
  367.             // key and we've figured out what key it was, and then set things up as such
  368.             // to properly dispatch.
  369.             
  370.             
  371.             if ( isCmdKey && ( (key >= 0x30) && (key <= 0x39)))
  372.             // translate ASCII Hex of this above line to decimal: 48 - 57, and char: 0 - 9
  373.             // hence why only key > 0x30...we can't have a cmd-0 item (just nine windows get
  374.             // cmd keys!)
  375.             {
  376.                 // they want to select a window from the windows menu. since this
  377.                 // window can constantly change in the menu (sometimes cmd-1 gives you
  378.                 // window 1 and other times (like after window 1 is closed) cmd-1 might
  379.                 // give you window 2) we do this to facilitate it all.
  380.             
  381.                 if ( key == 0x30 ) // so the cmd-0 doesn't fall through and print
  382.                     break;
  383.             
  384.                 HsoiDoSelectFromWindowsMenu( (short)((short)key - 48 + iFirstWindow - 1));
  385.             }
  386.             else if ( isCmdKey && (key >= 0x20) )    // is the command key down? (cmd+printable character
  387.                                                 // combos are routed to MenuKey())
  388.             {                                    // if so, do a menu command...
  389.                 HsoiAdjustMenus();
  390.                 HsoiDoMenuCommand( MenuKey( key ) );
  391.             }
  392.  
  393.             else if ( key == kHelpKey )  // or let's handle one special other case, the help key
  394.                                          // on the extended keyboard
  395.             {
  396.                 HsoiDoHelpStuff();
  397.             }
  398.             else
  399.             {                                // and all other keys, we'll just handle them "normally"
  400.                 HsoiDoKey( key, event );
  401.             }
  402.             
  403.         break;
  404.         
  405.         // end case keyDown/autoKey
  406.         
  407.         // activate events are simple enough...
  408.         
  409.         case activateEvt:
  410.             // remember, if it is a window related event, a reference to the window is stored
  411.             // in the event->message part of the EventRecord
  412.             HsoiDoActivate( (event->modifiers & activeFlag != 0 ), (WindowRef)event->message );
  413.         break;
  414.             
  415.         //    end case activatEvt
  416.             
  417.         
  418.         // update events are pretty easy to handle also...
  419.         
  420.         case updateEvt:
  421.             // as with the activateEvt, a reference to the window is stored in the
  422.             // EventRecord's message field
  423.             HsoiDoUpdate( (WindowRef)event->message );
  424.         break;
  425.             
  426.         //    end case updateEvt
  427.         
  428.         // if the user sticks a disk in that is unreadable (like an unformatted disk, or one
  429.         // formatted for another platform), let's put up stuff to deal with the disk.
  430.             
  431.         case diskEvt:
  432.             if ( HiWrd(event->message) != noErr )
  433.             {
  434.                 mountPoint.h = kDILeft;
  435.                 mountPoint.v = kDITop;
  436.                 myError = DIBadMount( mountPoint, event->message );
  437.             }
  438.         break;
  439.             
  440.         // end case diskEvt
  441.         
  442.         // this used to be called an app4Evt, but is now an osEvt (with the advent of MultiFinder/System 7)
  443.         // handles the backgrounding stuff (multitasking)
  444.         
  445.         case osEvt:
  446.             switch( (event->message >> 24) & 0x0FF )
  447.             {
  448.                 case suspendResumeMessage:
  449.                 
  450.                     window = FrontWindow();
  451.                     
  452.                     if ( ( event->message & resumeFlag ) == 0 ) // suspend
  453.                     {
  454.                         // if we have text speaking, stop it
  455.                         
  456.                         HsoiDoStop();
  457.                     
  458.                         // if we have a sound playing, stop it before we proceed.  it's
  459.                         // kinda "strange" to have your sound continuing playing while your
  460.                         // app is in the background...tho some people might want this *shrug*
  461.     
  462.                         if ( SoundIsPlaying() )
  463.                             StopCurrentSound();
  464.  
  465.                         gInBackground = true;
  466.                     }
  467.                     else // resuming
  468.                     {
  469.                         gInBackground = false;
  470.                         
  471.                         // remove any notification requests
  472.                         
  473.                         if ( gHasNotification )
  474.                             HsoiRemoveNMMessage();
  475.                         
  476.                     }
  477.                 
  478.                     // if there is a window, let's make sure to activate or deactivate it
  479.                     // so that all things look right on the screen.
  480.                     
  481.                     if ( window != nil )
  482.                         HsoiDoActivate( (event->message & resumeFlag ) != 0, window );
  483.                             
  484.                 break;
  485.  
  486.             
  487.                 case mouseMovedMessage:
  488.                 // do nothing
  489.                 break;
  490.  
  491.             } // end switch( event->message >> 24 ) & 0x0FF )
  492.         break;
  493.         
  494.         //     end case osEvt
  495.     }
  496.     
  497.     return;
  498. }
  499.  
  500.